import React, { FC, useRef, useState, useEffect } from 'react';
import { Row, Col, Space, Button, Slider } from 'antd';
import { ZoomInOutlined, ZoomOutOutlined } from '@ant-design/icons';
import _ from 'lodash';
import classnames from 'classnames';
import {
  FnButtonConfig,
  GraphConfig,
  shapeFn,
  defaultMyComponentRectConfig,
  menuConfig,
} from './config';
import { Graph, Addon } from '@antv/x6';
import '@antv/x6-react-shape';
import Node from './Node';
import { ToolLibrary } from './ToolLibrary';

let graph: Graph;
const ResourceTopology: FC = () => {
  const mountNode = useRef<HTMLDivElement>(null);
  const minmap = useRef<HTMLDivElement>(null);
  const stencil = useRef<HTMLDivElement>(null);
  const [sliderValue, setSliderValue] = useState<number>(1);
  const [selectRowKeys, setSelectRowKeys] = useState<string[]>([]);

  useEffect(() => {
    shapeFn();
    Custom_Node();
    create();
    graphEvents();
    // DrawingObj = new DrawingBoard('.x6-graph-svg');
  }, []);

  const sliderChange = (value) => {
    graph.zoomTo(value);
  };

  const Custom_Node = () => {
    // 注册 React 组件
    Graph.registerReactComponent(
      'react-node',
      (node) => {
        const data = node.getData();
        return <Node {...data} />;
      },
      true
    );
  };

  const zoomChange: (o: string) => void = (o) => {
    if (o === 'add') {
      graph.zoomTo(sliderValue + 0.01);
    } else {
      graph.zoomTo(sliderValue - 0.01);
    }
  };

  const create = () => {
    graph = new Graph({
      container: mountNode.current || undefined,
      minimap: {
        enabled: true,
        container: minmap.current || undefined,
      },

      ...GraphConfig,

      // 通过embedding可以将一个节点拖动到另一个节点中，使其成为另一节点的子节点，默认禁用。
      embedding: {
        enabled: true,
        findParent({ node }) {
          const bbox = node.getBBox();
          return graph.getNodes().filter((node) => {
            const data = node.getData<any>();
            if (data && data.parent) {
              const targetBBox = node.getBBox();
              return bbox.isIntersectWithRect(targetBBox);
            }
            return false;
          });
        },
      },
    });
  };

  const sliderProps = {
    vertical: true,
    reverse: true,
    tipFormatter: (value: number) => value + 'x',
    max: 3,
    min: 0.5,
    step: 0.01,
    onChange: sliderChange,
    value: sliderValue,
    marks: {
      1: '1x',
    },
  };

  const DeploymentCluster = () => {
    console.log(graph.getNodes());
  };

  const fnActionClicks = {
    DeploymentCluster,
  };

  const handlerClick = (v) => {
    if (selectRowKeys.indexOf(v) !== -1) {
      setSelectRowKeys(selectRowKeys.filter((o) => o !== v));
    } else {
      setSelectRowKeys([...selectRowKeys, v]);
    }
  };

  const onMouseDown = (e: React.MouseEvent<HTMLElement, MouseEvent>, node?) => {
    // dnd
    const dnd = new Addon.Dnd({
      target: graph,
      animation: true,
      validateNode(droppingNode, options) {
        let isValidateNode = true;

        return isValidateNode;
      },
    });
    if (!node) {
      const node = graph.createNode({
        data: {
          imgUrl: require(`./images/git.png`),
        },
        ...defaultMyComponentRectConfig,
      });

      dnd.start(node, e.nativeEvent);
    } else {
      const createNode = graph.createNode({
        ...node,
      });

      const newNode = createNode.clone();
      const { width, height } = newNode.size();
      dnd.start(
        newNode.setSize({
          width: width * 2,
          height: height * 2,
        }),
        e.nativeEvent
      );
    }
  };

  // 控制连接桩显示/隐藏
  const showPorts = (ports, show: boolean) => {
    for (let i = 0, len = ports.length; i < len; i = i + 1) {
      ports[i].style.visibility = show ? 'visible' : 'hidden';
    }
  };

  const graphEvents = () => {
    if (graph) {
      graph.on('scale', ({ sx, sy, ox, oy }) => {
        setSliderValue(sx);
      });
      graph.on('edge:connected', ({ edge, isNew }) => {
        if (isNew) {
          const source_node = edge.getSourceNode();
          const target_node = edge.getTargetNode();

          if (target_node) edge.setTarget(target_node);

          if (source_node) edge.setSource(source_node);
        }
      });
      graph.on('edge:mouseenter', ({ cell }) => {
        cell.addTools(
          [
            { name: 'vertices' },
            {
              name: 'button-remove',
              args: {
                distance: '50%',
                onClick: ({ e, cell, view }) => {
                  // const target_node = edge_get_nodes(cell, graph).target_node;
                  // const source_node = edge_get_nodes(cell, graph).source_node;

                  alert('暂不支持');
                },
              },
            },
          ],
          'onhover' // 工具集名称，可省略
        );
      });
      graph.on('edge:mouseleave', ({ cell }) => {
        if (cell.hasTools('onhover')) {
          cell.removeTools();
        }
      });

      graph.on('node:mouseenter', () => {
        const container: any = mountNode.current;
        if (container) {
          const ports = container.querySelectorAll('.x6-port-body');
          showPorts(ports, true);
        }
      });
      graph.on('node:mouseleave', () => {
        const container: any = mountNode.current;
        if (container) {
          const ports = container.querySelectorAll('.x6-port-body');
          showPorts(ports, false);
        }
      });

      graph.on('node:contextmenu', ({ node, cell, e }) => {
        // contextMenuActive = node;
      });

      graph.on('node:change:parent', ({ node }) => {
        console.log('父级关系发生变动');
      });

      graph.on('node:added', ({ node, index, options }) => {
        if (node.getData()?.parent) {
          node.setZIndex(0);
        }
      });

      graph.on('cell:dblclick', ({ cell, e }) => {
        const isNode = cell.isNode();
        const name = cell.isNode() ? 'node-editor' : 'edge-editor';
        console.log(cell);
        cell.removeTool(name);
        cell.addTools({
          name,
          args: {
            event: e,
            attrs: {
              backgroundColor: isNode ? '#EFF4FF' : '#FFF',
            },
          },
        });
      });
    }
  };

  const renderMenu = (data) => {
    return _.map(data, (item, key) => {
      const obj = { ...item };
      if (obj.children) {
        return (
          <div
            key={obj.id}
            className={classnames('widget-stencil', {
              collapsable: true,
              collapsed: selectRowKeys.indexOf(obj.id) !== -1,
            })}
          >
            <div
              className={'widget-stencil-title'}
              onClick={() => handlerClick(obj.id)}
            >
              {obj.title}
            </div>
            <div className="widget-stencil-content" onMouseDown={onMouseDown}>
              {renderMenu(obj.children)}
            </div>
          </div>
        );
      }
      return <div key={item.id}>{obj.title}</div>;
    });
  };

  return (
    <Row
      id="ResourceTopology"
      className="ClusterConstruction-layout ClusterConstruction-layout-v3"
    >
      <Col ref={stencil} id="stencil">
        <div className="title">资产库</div>
        <div className="content">{renderMenu(menuConfig)}</div>
        <div className="title">工具库</div>
        <div className="content svg-content">
          {_.map(ToolLibrary, (item) => {
            return (
              <span
                className="geItem"
                onMouseDown={(e) => onMouseDown(e, item.node)}
                key={item.id}
              >
                {item.elDom}
              </span>
            );
          })}
        </div>
      </Col>

      <Col
        className="graph-paper"
        ref={mountNode}
        id="ClusterConstruction-mountNode"
      ></Col>
      <div className="toolBtns___3r7m4">
        <Space id="toolbar">
          {_.map(FnButtonConfig, (item, key) => {
            return (
              <Button
                title={item.title}
                onClick={fnActionClicks[item.id]}
                key={item.id}
              >
                <span
                  className={classnames('iconfont button-icon', {
                    [item.iconClass]: true,
                  })}
                ></span>
                {item.title}
              </Button>
            );
          })}
        </Space>
      </div>
      <div className="toolZoom___2Zv_T">
        <Button
          shape="circle"
          title="放大视图"
          onClick={() => zoomChange('add')}
        >
          <ZoomInOutlined />
        </Button>
        <Slider {...sliderProps} />
        <Button
          shape="circle"
          title="缩小视图"
          onClick={() => zoomChange('reduce')}
        >
          <ZoomOutOutlined />
        </Button>
      </div>
      <div id="minmap" ref={minmap}></div>
    </Row>
  );
};

export default ResourceTopology;
